﻿using System.Diagnostics;
// ReSharper disable CanSimplifyDictionaryTryGetValueWithGetValueOrDefault

namespace KinonekoSoftware.Extensions.Strings.SearchModels.TrieTree
{
    [DebuggerTypeProxy(typeof(NodeDebuggerView))]
    internal class Node(char value)
    {

        internal readonly Dictionary<char, Node> Children = new Dictionary<char, Node>();
        internal readonly char                   Value    = value;


        internal          bool IsWordEnd;
        internal          Node Fail;
        internal required Node Parent;

        public void Remove(Node child)
        {
            //
            //
            Children.Remove(child.Value);
        }

        public Node GetOrCreate(char key)
        {
            if (!Children.TryGetValue(key, out var child))
            {
                child = new Node(key)
                {
                    Depth  = (byte)(Depth + 1),
                    Parent = this,
                };
                Children.Add(key, child);
            }

            //
            //
            return child;
        }
        
        public Node Get(char key)
        {
            // 使用下列代码比直接调用 Children.GetValueOrDefault(key)，耗时少了23%。
            if (Children.TryGetValue(key, out var child))
            {
                return child;
            }

            return null;
        }

        private string DebuggerValue      => Value.ToString();
        private string DebuggerValueFail  => (Fail?.Value)?.ToString() ?? "null";
        private int    DebuggerValueDepth => Depth;
        private int    DebuggerValueCount => Children.Count;
        
        internal required byte Depth { get; init; }
        internal          bool IsRoot      => Value          == '$';
        internal          bool HasChildren => Children.Count > 0;

        internal char FailValue => Fail?.Value ?? '\x20';
        
        
        public override string ToString()
        {
            if (HasChildren)
            {
                return $"[@{DebuggerValue} -{DebuggerValueDepth}] -> {DebuggerValueFail}";
            }
            return $"[@{DebuggerValue} -{DebuggerValueDepth}]({DebuggerValueCount}) -> {DebuggerValueFail}";
        }
    }


    internal class NodeDebuggerView(Node _node)
    {
        
        
        public IEnumerable<string> Children
        {
            get
            {
                return _node.Children.Select(child => child.Value.ToString());
            }
        }


        public override string ToString() => _node.ToString();
    }
}